package org.hs.phd.odi.tracking.ui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import org.hs.phd.common.frameviewer.DefaultFrameViewerImpl;
import org.hs.phd.common.frameviewer.FrameViewer;
import org.hs.phd.common.frameviewer.ViewerLayer;
import org.hs.phd.odi.tracking.ui.trackInitialization.RectangleSelectionTrackInitiationLayer;
import org.hs.phd.odi.tracking.ui.trackInitialization.TrackInitializationListener;


public class DefaultTrackingView implements TrackingView, TrackInitializationListener {
	
	private TrackingPresenter presenter;
	private JFrame window;
	private FrameViewer frameViewer;
	private TracksLayer tracksLayer;
	private ViewerLayer trackInitiationLayer;
	private JButton btnPlayPause;
	private JButton btnPrev;
	private JButton btnNext;
	private JButton btnZoomIn;
	private JButton btnZoomOut;
	private TrackingModel model;
	private boolean isFirstFrame;

	public DefaultTrackingView(){
		isFirstFrame = true;
		contructGUI();
	}

	private void contructGUI() {
		window = new JFrame("Omni Directional Tracking");
		frameViewer = new DefaultFrameViewerImpl();

		tracksLayer = new TracksLayer();
		
		//trackInitiationLayer = new FixedWindowTrackInitiationLayer(this, 20, 20);
		trackInitiationLayer = new RectangleSelectionTrackInitiationLayer(this);
		trackInitiationLayer.setEnabled(true);

		frameViewer.addLayer(tracksLayer);
		frameViewer.addLayer(trackInitiationLayer);
		frameViewer.setScale(0.75f);
		//frameViewer.setScale(1);
		
		JPanel pnlButtons = new JPanel( new FlowLayout(FlowLayout.LEFT) );
		pnlButtons.setBorder( BorderFactory.createEtchedBorder());
		
		btnPlayPause = new JButton("Play/Pause");
		btnPrev = new JButton("Prev");
		btnNext = new JButton("Next");
		btnZoomIn = new JButton("+");
		btnZoomOut = new JButton("-");

		btnPlayPause.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				tooglePause();
			}
		});

		btnPrev.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				presenter.onStepPreviousFrame();
			}
		});

		btnNext.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				presenter.onStepNextFrame();
			}
		});

		btnZoomIn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				frameViewer.zoomIn();
			}
		});

		btnZoomOut.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				frameViewer.zoomOut();
			}
		});

		
		pnlButtons.add(btnPrev);
		pnlButtons.add(btnNext);
		pnlButtons.add(btnPlayPause);
		pnlButtons.add(new JButton("Clear Track"));
		pnlButtons.add(btnZoomIn);
		pnlButtons.add(btnZoomOut);

		JPanel pnlViewer = new JPanel(new BorderLayout());
		pnlViewer.setBorder( BorderFactory.createEtchedBorder());
		pnlViewer.add(frameViewer.getUI(), BorderLayout.CENTER);
		
		window.getContentPane().add(pnlButtons, BorderLayout.NORTH);
		window.getContentPane().add(pnlViewer, BorderLayout.CENTER);
		
		window.addWindowListener(new WindowAdapter() {

			@Override
			public void windowOpened(WindowEvent e) {
				if(presenter != null){
					presenter.onStartup();
				}
			}

			@Override
			public void windowClosing(WindowEvent e) {
				if(presenter != null){
					presenter.onClose();
				}
			}

		});
		
	}

	private void tooglePause() {
		if( presenter.isPaused() ){
			trackInitiationLayer.setEnabled(false);
			presenter.onResume();
		}else{
			trackInitiationLayer.setEnabled(true);
			presenter.onPause();
		}
		updateButtonStates();
	}

	@Override
	public void setPresenter(TrackingPresenter presenter) {
		this.presenter = presenter;
		
		updateButtonStates();
	}

	private void updateButtonStates() {
		if(presenter != null){
			boolean paused = presenter.isPaused();
			btnPrev.setEnabled(paused);
			btnNext.setEnabled(paused);
			btnPlayPause.setText(paused ? "Play" : "Pause");
		}
	}

	@Override
	public void dispose() {
		window.dispose();
	}

	@Override
	public void show() {
		window.pack();
		window.setVisible(true);
	}

	@Override
	public void updateModel(final TrackingModel model) {
		
		if( SwingUtilities.isEventDispatchThread() ){
			updateModelInEDT(model);
		}else{
			try {
				SwingUtilities.invokeAndWait(new Runnable() {
					
					@Override
					public void run() {
						updateModelInEDT(model);
					}
				});
			} catch (InterruptedException e) {
				// do nothing
			} catch (InvocationTargetException e) {
				throw new RuntimeException(e);
			}
		}
	}

	private void updateModelInEDT(TrackingModel model) {
		
		this.model = model;
		frameViewer.setImage(model.getImage());
		tracksLayer.setTracks(model.getTracks());
		updateButtonStates();

		if(isFirstFrame){
			isFirstFrame = false;
			window.invalidate();
			window.pack();
		}
		
	}

	@Override
	public void trackInitialized(Polygon polygon) {
		presenter.onTrackStarted(polygon, model.getImage());
	}

}
